package com.ld.poetry.service.impl;

import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ld.poetry.config.PoetryResult;
import com.ld.poetry.constants.CommonConst;
import com.ld.poetry.dao.ArticleMapper;
import com.ld.poetry.dao.CommentMapper;
import com.ld.poetry.entity.Article;
import com.ld.poetry.entity.Comment;
import com.ld.poetry.entity.User;
import com.ld.poetry.enums.CodeMsg;
import com.ld.poetry.enums.CommentTypeEnum;
import com.ld.poetry.service.CommentService;
import com.ld.poetry.utils.*;
import com.ld.poetry.utils.mail.MailSendUtil;
import com.ld.poetry.vo.BaseRequestVO;
import com.ld.poetry.vo.CommentVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 文章评论表 服务实现类
 * </p>
 *
 * @author sara
 * @since 2021-08-13
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements CommentService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private CommonQuery commonQuery;

    @Autowired
    private MailSendUtil mailSendUtil;

    /**
     * 保存评论
     * 
     * 该方法用于保存用户提交的评论，主要功能包括：
     * 1. 验证评论类型是否合法
     * 2. 如果是文章评论，验证文章是否存在且评论功能是否开启
     * 3. 保存评论信息到数据库
     * 4. 发送评论通知邮件
     * 
     * @param commentVO 评论视图对象，包含评论相关信息
     * @return PoetryResult 操作结果
     *         - 成功：返回成功信息
     *         - 失败：返回错误信息（评论类型不存在/文章不存在/评论功能已关闭）
     */
    @Override
    public PoetryResult saveComment(CommentVO commentVO) {
        // 验证评论类型是否合法
        if (CommentTypeEnum.getEnumByCode(commentVO.getType()) == null) {
            return PoetryResult.fail("评论来源类型不存在！");
        }

        // 如果是文章评论，需要验证文章信息
        Article one = null;
        if (CommentTypeEnum.COMMENT_TYPE_ARTICLE.getCode().equals(commentVO.getType())) {
            // 查询文章信息，只查询必要的字段
            LambdaQueryChainWrapper<Article> articleWrapper = new LambdaQueryChainWrapper<>(articleMapper);
            one = articleWrapper.eq(Article::getId, commentVO.getSource())
                    .select(Article::getUserId, Article::getArticleTitle, Article::getCommentStatus)
                    .one();

            // 验证文章是否存在
            if (one == null) {
                return PoetryResult.fail("文章不存在");
            } else {
                // 验证文章评论功能是否开启
                if (!one.getCommentStatus()) {
                    return PoetryResult.fail("评论功能已关闭！");
                }
            }
        }

        // 构建评论实体对象
        Comment comment = new Comment();
        // 设置评论基本信息
        comment.setSource(commentVO.getSource());
        comment.setType(commentVO.getType());
        comment.setCommentContent(commentVO.getCommentContent());
        // 设置评论关系信息
        comment.setParentCommentId(commentVO.getParentCommentId());
        comment.setFloorCommentId(commentVO.getFloorCommentId());
        comment.setParentUserId(commentVO.getParentUserId());
        // 设置评论用户信息
        comment.setUserId(PoetryUtil.getUserId());
        // 设置评论附加信息（如果有）
        if (StringUtils.hasText(commentVO.getCommentInfo())) {
            comment.setCommentInfo(commentVO.getCommentInfo());
        }
        // 保存评论到数据库
        save(comment);

        // 异步发送评论通知邮件
        try {
            mailSendUtil.sendCommentMail(commentVO, one, this);
        } catch (Exception e) {
            // 邮件发送失败不影响评论保存，记录错误日志
            log.error("发送评论邮件失败：", e);
        }

        return PoetryResult.success();
    }

    /**
     * 删除评论
     * 
     * 该方法用于删除用户自己的评论，主要功能包括：
     * 1. 获取当前登录用户ID
     * 2. 根据评论ID和用户ID删除评论
     * 3. 返回操作结果
     * 
     * 注意：
     * - 只能删除自己的评论
     * - 删除操作是物理删除
     * - 删除评论不会影响子评论
     * 
     * @param id 要删除的评论ID
     * @return PoetryResult 操作结果
     *         - 成功：返回成功信息
     *         - 失败：返回错误信息（评论不存在/无权限删除）
     */
    @Override
    public PoetryResult deleteComment(Integer id) {
        // 获取当前登录用户ID
        Integer userId = PoetryUtil.getUserId();
        
        // 根据评论ID和用户ID删除评论
        // 使用lambdaUpdate确保只能删除自己的评论
        lambdaUpdate()
                .eq(Comment::getId, id)        // 评论ID匹配
                .eq(Comment::getUserId, userId) // 用户ID匹配
                .remove();                      // 执行删除操作

        return PoetryResult.success();
    }

    /**
     * 查询评论列表
     * 
     * 该方法用于查询评论列表，支持两种查询模式：
     * 1. 查询主评论列表（包含子评论）
     * 2. 查询指定楼层的子评论列表
     * 
     * 主要功能包括：
     * 1. 参数验证
     * 2. 文章评论功能验证
     * 3. 分页查询评论
     * 4. 构建评论视图对象
     * 5. 查询子评论（如果是主评论）
     * 
     * @param baseRequestVO 查询参数对象，包含：
     *                     - source: 评论来源ID
     *                     - commentType: 评论类型
     *                     - floorCommentId: 楼层评论ID（可选）
     * @return PoetryResult<BaseRequestVO> 查询结果
     *         - 成功：返回分页的评论列表
     *         - 失败：返回错误信息（参数错误/评论功能已关闭）
     */
    @Override
    public PoetryResult<BaseRequestVO> listComment(BaseRequestVO baseRequestVO) {
        // 参数验证
        if (baseRequestVO.getSource() == null || !StringUtils.hasText(baseRequestVO.getCommentType())) {
            return PoetryResult.fail(CodeMsg.PARAMETER_ERROR);
        }

        // 如果是文章评论，验证文章评论功能是否开启
        if (CommentTypeEnum.COMMENT_TYPE_ARTICLE.getCode().equals(baseRequestVO.getCommentType())) {
            LambdaQueryChainWrapper<Article> articleWrapper = new LambdaQueryChainWrapper<>(articleMapper);
            Article one = articleWrapper.eq(Article::getId, baseRequestVO.getSource())
                    .select(Article::getCommentStatus)
                    .one();

            if (one != null && !one.getCommentStatus()) {
                return PoetryResult.fail("评论功能已关闭！");
            }
        }

        // 根据是否指定楼层评论ID，选择不同的查询方式
        if (baseRequestVO.getFloorCommentId() == null) {
            // 查询主评论列表（parentCommentId = 0）
            lambdaQuery()
                    .eq(Comment::getSource, baseRequestVO.getSource())
                    .eq(Comment::getType, baseRequestVO.getCommentType())
                    .eq(Comment::getParentCommentId, CommonConst.FIRST_COMMENT)
                    .orderByDesc(Comment::getCreateTime)
                    .page(baseRequestVO);

            List<Comment> comments = baseRequestVO.getRecords();
            if (CollectionUtils.isEmpty(comments)) {
                return PoetryResult.success(baseRequestVO);
            }

            // 构建评论视图对象，并查询子评论
            List<CommentVO> commentVOs = comments.stream().map(c -> {
                CommentVO commentVO = buildCommentVO(c);
                // 查询子评论（每页5条）
                Page page = new Page(1, 5);
                lambdaQuery()
                        .eq(Comment::getSource, baseRequestVO.getSource())
                        .eq(Comment::getType, baseRequestVO.getCommentType())
                        .eq(Comment::getFloorCommentId, c.getId())
                        .orderByAsc(Comment::getCreateTime)
                        .page(page);

                List<Comment> childComments = page.getRecords();
                if (childComments != null) {
                    // 构建子评论视图对象
                    List<CommentVO> ccVO = childComments.stream()
                            .map(cc -> buildCommentVO(cc))
                            .collect(Collectors.toList());
                    page.setRecords(ccVO);
                }
                commentVO.setChildComments(page);
                return commentVO;
            }).collect(Collectors.toList());

            baseRequestVO.setRecords(commentVOs);
        } else {
            // 查询指定楼层的子评论列表
            lambdaQuery()
                    .eq(Comment::getSource, baseRequestVO.getSource())
                    .eq(Comment::getType, baseRequestVO.getCommentType())
                    .eq(Comment::getFloorCommentId, baseRequestVO.getFloorCommentId())
                    .orderByAsc(Comment::getCreateTime)
                    .page(baseRequestVO);

            List<Comment> childComments = baseRequestVO.getRecords();
            if (CollectionUtils.isEmpty(childComments)) {
                return PoetryResult.success(baseRequestVO);
            }

            // 构建子评论视图对象
            List<CommentVO> ccVO = childComments.stream()
                    .map(cc -> buildCommentVO(cc))
                    .collect(Collectors.toList());
            baseRequestVO.setRecords(ccVO);
        }

        return PoetryResult.success(baseRequestVO);
    }

    /**
     * 管理员查询评论列表
     * 
     * 该方法用于管理员查询评论列表，支持两种查询模式：
     * 1. Boss模式：可以查询所有评论
     * 2. 普通用户模式：只能查询自己文章的评论
     * 
     * 主要功能包括：
     * 1. 根据用户权限构建不同的查询条件
     * 2. 支持按来源和类型筛选
     * 3. 分页查询评论列表
     * 
     * @param baseRequestVO 查询参数对象，包含：
     *                     - source: 评论来源ID（可选）
     *                     - commentType: 评论类型（可选）
     * @param isBoss 是否为Boss权限
     * @return PoetryResult<Page> 查询结果
     *         - 成功：返回分页的评论列表
     *         - 失败：返回错误信息
     */
    @Override
    public PoetryResult<Page> listAdminComment(BaseRequestVO baseRequestVO, Boolean isBoss) {
        // 构建查询条件
        LambdaQueryChainWrapper<Comment> wrapper = lambdaQuery();

        if (isBoss) {
            // Boss模式：可以查询所有评论
            if (baseRequestVO.getSource() != null) {
                // 按来源筛选
                wrapper.eq(Comment::getSource, baseRequestVO.getSource());
            }
            if (StringUtils.hasText(baseRequestVO.getCommentType())) {
                // 按评论类型筛选
                wrapper.eq(Comment::getType, baseRequestVO.getCommentType());
            }
            // 按创建时间降序排序并分页
            wrapper.orderByDesc(Comment::getCreateTime)
                    .page(baseRequestVO);
        } else {
            // 普通用户模式：只能查询自己文章的评论
            // 获取用户的所有文章ID
            List<Integer> userArticleIds = commonQuery.getUserArticleIds(PoetryUtil.getUserId());
            
            if (CollectionUtils.isEmpty(userArticleIds)) {
                // 用户没有文章，返回空结果
                baseRequestVO.setTotal(0);
                baseRequestVO.setRecords(new ArrayList());
            } else {
                if (baseRequestVO.getSource() != null) {
                    // 查询指定文章的评论
                    wrapper.eq(Comment::getSource, baseRequestVO.getSource())
                            .eq(Comment::getType, CommentTypeEnum.COMMENT_TYPE_ARTICLE.getCode());
                } else {
                    // 查询用户所有文章的评论
                    wrapper.eq(Comment::getType, CommentTypeEnum.COMMENT_TYPE_ARTICLE.getCode())
                            .in(Comment::getSource, userArticleIds);
                }
                // 按创建时间降序排序并分页
                wrapper.orderByDesc(Comment::getCreateTime)
                        .page(baseRequestVO);
            }
        }

        return PoetryResult.success(baseRequestVO);
    }

    /**
     * 构建评论视图对象
     * 
     * 该方法用于将评论实体对象转换为评论视图对象，主要功能包括：
     * 1. 复制基本属性
     * 2. 查询并设置评论用户信息
     * 3. 查询并设置父评论用户信息
     * 4. 处理用户名显示（如果用户名为空，使用随机名称）
     * 
     * @param c 评论实体对象
     * @return CommentVO 评论视图对象，包含：
     *         - 评论基本信息
     *         - 评论用户信息（用户名、头像）
     *         - 父评论用户信息（用户名）
     */
    private CommentVO buildCommentVO(Comment c) {
        // 创建评论视图对象并复制基本属性
        CommentVO commentVO = new CommentVO();
        BeanUtils.copyProperties(c, commentVO);

        // 查询并设置评论用户信息
        User user = commonQuery.getUser(commentVO.getUserId());
        if (user != null) {
            commentVO.setAvatar(user.getAvatar());
            commentVO.setUsername(user.getUsername());
        }

        // 如果用户名为空，使用随机名称
        if (!StringUtils.hasText(commentVO.getUsername())) {
            commentVO.setUsername(PoetryUtil.getRandomName(commentVO.getUserId().toString()));
        }

        // 如果存在父评论用户，查询并设置父评论用户信息
        if (commentVO.getParentUserId() != null) {
            User parentUser = commonQuery.getUser(commentVO.getParentUserId());
            if (parentUser != null) {
                commentVO.setParentUsername(parentUser.getUsername());
            }
            // 如果父评论用户名为空，使用随机名称
            if (!StringUtils.hasText(commentVO.getParentUsername())) {
                commentVO.setParentUsername(PoetryUtil.getRandomName(commentVO.getParentUserId().toString()));
            }
        }

        return commentVO;
    }
}
